 package com.gmrz.uaf.common.service.challengestore;
 
 import com.gmrz.service.challengestore.ChallengeStoreException;
import com.gmrz.service.challengestore.ChallengeStoreService;
import com.gmrz.uaf.common.Constants;
 import com.gmrz.uaf.common.GuiceUtil;
 import com.gmrz.uaf.db.DAOException;
 import com.gmrz.uaf.db.DAOFactory;
 import com.gmrz.uaf.db.UAFDAOFactory;
 import com.gmrz.uaf.db.UAFDBConnectionMgr;
import com.gmrz.uaf.db.dao.BaseWhiteListDAO;
 import com.gmrz.uaf.db.dao.WhiteListDAO;
 import com.gmrz.uaf.protocol.v1.processor.exception.UAFErrorCode;
import com.gmrz.uaf.protocol.v1.schema.WhiteList;
import com.gmrz.uaf.server.ServerConfig;
import com.gmrz.util.db.DBUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
 
 @Singleton
 public class UAFChallengeStoreServiceProvider
   implements Provider<ChallengeStoreService>
 {
   private static final Logger LOG = LogManager.getLogger(UAFChallengeStoreServiceProvider.class);
 
   private ChallengeStoreService mChallengeStoreService = null;
   private Properties mUafProperties = null;
   private ServerConfig mServerConfig = null;
 
   @Inject
   public UAFChallengeStoreServiceProvider(@Named("uaf.properties") Properties uafProperties, ServerConfig serverConfig)
   {
     LOG.info("Creating instance of UAFChallengeStoreServiceProvider");
     this.mUafProperties = uafProperties;
     this.mServerConfig = serverConfig;
   }
 
   public ChallengeStoreService get()
   {
     if (this.mChallengeStoreService == null) {
       synchronized (UAFChallengeStoreServiceProvider.class) {
         if (this.mChallengeStoreService == null)
         {
           LOG.info("Load and init the challengeStoreService");
           init();
         }
       }
     }
     return this.mChallengeStoreService;
   }
 
   private void init()
   {
     loadChallengeStoreService(this.mServerConfig);
 
     if (this.mUafProperties == null) {
       LOG.error("Failed to Initialize the challengeStoreService, uafProperties is NULL");
       throw new UAFChallengeStoreServiceException("Failed to Initialize the challengeStoreService, uafProperties is NULL");
     }
     if (this.mChallengeStoreService == null) {
       LOG.error("Unable to initialize NULL challengeStoreService");
       throw new UAFChallengeStoreServiceException("Unable to initialize NULL challengeStoreService");
     }
 
     try
     {
       this.mChallengeStoreService.init(this.mUafProperties);
       this.mChallengeStoreService.initCache(this.mUafProperties);
       List<WhiteList> whiteList = queryWhiteList();
       if(whiteList!=null && !whiteList.isEmpty()){
         this.mChallengeStoreService.setWhiteList(Constants.WHITE_LIST_KEY,whiteList);
       }else{
         LOG.warn("There is no any white list configuration in database");
       }

     } catch (ChallengeStoreException ex) {
       LOG.error("Error in initializing the challenge store service", ex);
       throw new UAFChallengeStoreServiceException(ex);
     } catch (Exception error) {
       LOG.error("Unexpected Error in initializing the challenge store service", error);
       throw new UAFChallengeStoreServiceException("Unexpected Error in initializing the challenge store service", error);
     }
   }
 
   private void loadChallengeStoreService(ServerConfig serverConfig) {
     String challengeStoreServiceClassName = serverConfig.getChallengeStoreServiceClassName();
     if ((challengeStoreServiceClassName != null) && (!challengeStoreServiceClassName.trim().isEmpty()))
       try
       {
         // 通过反射获取 redis 缓存连接，new Class[0] ：是为了告诉反射获取无参构造，使用其可防止产生空指针的异常
         this.mChallengeStoreService = (ChallengeStoreService)Class.forName(challengeStoreServiceClassName.trim()).getConstructor(new Class[0]).newInstance();
 
         LOG.info("Using challengeStoreService implementation : {} ", this.mChallengeStoreService.getClass().getName());
       }
       catch (Exception error)
       {
         LOG.error("Failed to load the challengeStoreService class - {}, Error : {}", challengeStoreServiceClassName, error.getMessage());
 
         throw new UAFChallengeStoreServiceException(error);
       }
   }

   private List<WhiteList> queryWhiteList() throws DAOException {
     Connection connection=null;
     try{
          connection= UAFDBConnectionMgr.getConnection(true);
//          WhiteListDAO dao = GuiceUtil.getProcessorInjector().getInstance(DAOFactory.class).createWhiteListDAO(connection);
       WhiteListDAO dao = UAFDAOFactory.createWhiteListDAO(connection);
       return dao.list();
     }catch(SQLException sqle){
       LOG.error(sqle);
       throw new DAOException(UAFErrorCode.DB_DATABASE_CONNECTION_ERROR,sqle);
     } finally {
       DBUtil.close(connection);
     }
   }
 }
